package com.cloneoner.test.slider.view
{
	import com.greensock.OverwriteManager;
	import flash.geom.Matrix;
	import com.greensock.TweenLite;
	import flash.filters.BlurFilter;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.events.MouseEvent;
	import flash.display.DisplayObject;

	import fr.digitas.flowearth.command.Batcher;
	import fr.digitas.flowearth.ui.layout.Layout;
	import fr.digitas.flowearth.ui.layout.renderer.LeftRenderer;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.geom.Rectangle;


	/**
	 * @author Thibault Loup
	 */
	public class SliderBmpdBlur extends Sprite
	{

		// __________________________________________________________
		// -										 	  CONSTRUCTOR
		public function SliderBmpdBlur(pWidth : int, pHeight : int, pGap : int, pCoeffSlide:uint=3, pCoeffBlur:Number=.2, pMinBlur:uint = 10)
		{
			_WIDTH = pWidth;
			_HEIGHT = pHeight;
			_gap = pGap;
			_coeff = pCoeffSlide;
			_coeffBlur = pCoeffBlur;
			_blurValueMin = pMinBlur;

			_build();
			_initVars();
		}
		
		// __________________________________________________________
		// -										  PUBLICS METHODS
		
		public function load() : void
		{
			if ( _batcher)
			{
				_batcher.dispose();
				_batcher = null;
			}
			
			_batcher = new Batcher();
			
			var i : int;
			var ln : int = _content.numChildren;
			var it : DisplayObject;
			
			while (i < ln)
			{
				it = _content.getChildAt(i);
				if ( it is ItemImg )
				{
					if ( ItemImg(it).getLoadables())
						_batcher.addItem(ItemImg(it).getLoadables());
				}
				++i;
			}
			
			_batcher.start();
		}
		
		public function addItem(pItem : DisplayObject) : void
		{
			_content.addChild(pItem);
			_content.update();
			
			_minPos = - (_content.container.width-_WIDTH);
			_minPos = _minPos > 0 ? 0 : _minPos;
		}
		
		public function dispose() : void
		{
			removeEventListener(Event.ADDED_TO_STAGE, _onAdded);
			removeEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
			removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
			
			while(numChildren)removeChildAt(0);
			
			if( _stage)
				_stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
			
			if( _bmpd) _bmpd.dispose();
			
			if( _content)
			{
				var c:ItemImg;
				
				while(_content.numChildren)
				{
					c = _content.getChildAt(0) as ItemImg;
					c.dispose();
					c = null;
				}
			}
			
			if( _batcher ) _batcher.dispose();
			
			_content = null;
			_batcher = null;
			_bmpd = null;
			_stage = null;
		}


		// __________________________________________________________
		// -										 		   EVENTS

		private function _onMouseDown(event : MouseEvent) : void
		{	
			_lastClick.x = this.mouseX;
			_lastClick.y = this.mouseY;
			
			_lastPos = this.mouseX;
			
			_content.visible = false;
			_bmp.visible = true;
			
			_stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
			addEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
		
		private function _onMouseUp(event : MouseEvent) : void
		{
			var delta:Number = this.mouseX - _lastPos;
			var xx:Number = _content.x + delta*_coeff;
			
			var p:Point = new Point(this.mouseX, this.mouseY);
			var d:Number = Point.distance(p, _lastClick);
			
			if(d < 3)
			{
				
			}
			else
			{
				_moveTo(xx);
			}
			
			_stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
			removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
		
		private function _onEnterFrame(e:Event):void
		{
			var delta:Number = this.mouseX - _lastPos;
			
			_content.x += delta * _coeffDrag;
			
			_lastPos = this.mouseX;
			
			_draw();
		}

		// __________________________________________________________
		// -										 PRIVATES METHODS
		private function _build() : void
		{
			_content = new Layout();
			_content.renderer = new LeftRenderer();
			_content.margin = new Rectangle(0, 0, _gap);
			addChild(_content);

			addChild(_bmp = new Bitmap());
			_bmpd = new BitmapData(_WIDTH, _HEIGHT, true, 0);

			buttonMode = useHandCursor = true;
			mouseChildren = true;

			this.scrollRect = new Rectangle(0, 0, _WIDTH, _HEIGHT);

			addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
			addEventListener(Event.ADDED_TO_STAGE, _onAdded);
		}
		
		private function _draw():void
		{	
			_bmpd.lock();
			
//			_bmpd.fillRect(_rect, 0);
			
			var mat:Matrix = new Matrix();
			mat.tx = _content.x;
			
			_bmpd.draw(_content, mat);
			
			_bmpd.applyFilter(_bmpd, _rect, _point, _blur);
			
			_bmpd.unlock();
			
			_bmp.bitmapData = _bmpd;
		}
		
		private function _onAdded(event : Event) : void
		{
			_stage = stage;
		}
		
		private function _initVars():void
		{
			OverwriteManager.init();
			
			_lastClick = new Point();
			_lastPos = _content.x;
			
			_rect = new Rectangle(0, 0, _WIDTH, _HEIGHT);
			_point = new Point();
			_blur = new BlurFilter(0, 0);
		}
		
		private function _moveTo(pValue:Number):void
		{
			var xx:int = pValue > _maxPos ? _maxPos : pValue;
			xx = pValue < _minPos ? _minPos : xx;
			
			var delta:Number = _content.x - xx;
			delta = delta < 0 ? -delta : delta;
			
			var b:int = delta * _coeffBlur;
			b = b < _blurValueMin ? 0 : b;
			
			TweenLite.killTweensOf(_content);
			TweenLite.killTweensOf(_blur);
			
			TweenLite.to( _blur, .2, {blurX:b});
			TweenLite.to( _blur, .2, {blurX:0, delay:.2});
			TweenLite.to(_content, .4, {x:xx, onUpdate:_draw});
		}
		
		
		
		/* CONTENT */
		private var _content : Layout;
		private var _bmp : Bitmap;
		private var _bmpd : BitmapData;
		
		/* VAR */
		private var _batcher : Batcher;
		private var _stage:Stage;
		
		private var _lastClick:Point;
		private var _lastPos:Number;
		private var _minPos:int;
		private const _maxPos:int = 0;
		
		// filter
		private var _rect:Rectangle;
		private var _point:Point;
		private var _blur:BlurFilter;
		
		private var _blurValueMin:int = 20;
		private var _coeffBlur:Number = 0.5;
		private var _coeff:uint = 5;
		
		private var _gap : int;
		private var _WIDTH : int;
		private var _HEIGHT : int;
		
		private const _coeffDrag:Number = 1;
	}
}